package com.workingpub.commons.jdbc.builder.ognl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

/**
 * Caches OGNL parsed expressions
 * 
 * @author taoping
 *
 */
public class OgnlCache {
	private static final Map<String, Object> expressionCache = new ConcurrentHashMap<String, Object>();

	private OgnlCache() {

	}

	public static Object getValue(String expression, Object root) {
		Object result = null;
		try {
			Map<?, ?> context = Ognl.createDefaultContext(root, new OgnlClassResolver());
			result = Ognl.getValue(parse(expression), context, root);
		} catch (OgnlException e) {
			Assert.notNull(e, "Error evaluating expression '" + expression + "'. Cause: " + e.getMessage());
		}
		return result;
	}

	public static Object getValue(String expression, Object root, Map<String, Object> others) {
		Object result = null;
		try {
			OgnlContext context = (OgnlContext) Ognl.createDefaultContext(root, new OgnlClassResolver());
			if (!CollectionUtils.isEmpty(others)) {
				context.putAll(others);
			}
			result = Ognl.getValue(parse(expression), context, root);
		} catch (OgnlException e) {
			Assert.notNull(e, "Error evaluating expression '" + expression + "'. Cause: " + e.getMessage());
		}
		return result;
	}

	private static Object parse(String expression) throws OgnlException {
		if (expressionCache.containsKey(expression)) {
			return expressionCache.get(expression);
		} else {
			Object node = Ognl.parseExpression(expression);
			expressionCache.put(expression, node);
			return node;
		}
	}
}
